package RuleProbabilityStore

import (
	"gitee.com/tym_hmm/go-helper/RandomHelper"
	"gitee.com/yebetter/lucky-draw/Conf"
	"gitee.com/yebetter/lucky-draw/Core/App/Log"
	"gitee.com/yebetter/lucky-draw/Core/Error"
	"strings"
)

/**
概率算法库存算法
*/
type ruleProbabilityStore struct {
	*Conf.BaseDraw

	//重设后的奖项数据
	probabilityData map[string]*Conf.AwardItem

	//保存每个奖项的权限
	probabilityVal map[string]int
	//奖项总权总
	probabilitySum int
}

func NewRuleProbabilityStore() *ruleProbabilityStore {
	return &ruleProbabilityStore{
		BaseDraw:        &Conf.BaseDraw{AwardData: []*Conf.AwardItem{}, Identification: Conf.LUCKY_DRAW_RULE_TYPE_PROBABILITY_STORE},
		probabilityData: make(map[string]*Conf.AwardItem),
		probabilityVal:  make(map[string]int),
		probabilitySum:  0,
	}
}

func (this *ruleProbabilityStore) GetIdentifier() Conf.LUCKY_DRAW_RULE_TYPE {
	return this.Identification
}

func (this *ruleProbabilityStore) SetEventHandle(eventHandle Conf.EventHandle) {
	this.EventHandle = eventHandle
}

func (this *ruleProbabilityStore) SetAward(award []*Conf.AwardItem) {
	this.AwardData = award
}

func (this *ruleProbabilityStore) Handle() (*Conf.AwardResult, *Error.Errno) {
	response, err := this.run()
	//Log.AppLog.Debug("ruleProbabilityStore [ 奖项 => %+v ]", response)
	return response, err
}

/**
执行抽奖
*/
func (this *ruleProbabilityStore) run() (*Conf.AwardResult, *Error.Errno) {
	this.setProbability()
	serialNumberTemp := this.algorithm()
	if len(strings.TrimSpace(serialNumberTemp)) == 0 {
		return Conf.LOSING_LOTTERY, nil
	}

	result := &Conf.AwardResult{}
	allResult := &Conf.AwardItem{}

	if val, ok := this.probabilityData[serialNumberTemp]; ok {
		allResult = val
		result = &Conf.AwardResult{
			Name:         val.Name,
			SerialNumber: val.SerialNumber,
			DataMap:      val.DataMap,
		}
	} else {
		allResult = nil
		result = Conf.LOSING_LOTTERY
	}

	//上传
	if this.EventHandle != nil && allResult != nil {
		Log.AppLog.Debug(" ruleProbabilityStore [ allResult.Name => %s, allResult.NftHash => %s ]", allResult.Name, allResult.NftHash)
		//@param awardName string 奖品名称
		//	@param awardTag string 奖品标识
		//	@param typeCode int 标识
		errs := this.EventHandle.AwardUpload(allResult.Name, allResult.NftHash)
		if errs != nil {
			Log.AppLog.Debug("ruleProbabilityStore [errs => %+v ]", errs)
			return nil, errs
		}
	}

	//最终结果处理
	if this.EventHandle != nil {
		this.EventHandle.Result(serialNumberTemp, allResult, result)
	}
	return result, nil
}

/**
重设数据
根据权限及库存处理
*/
func (this *ruleProbabilityStore) setProbability() {
	//如果没有数据
	for _, v := range this.AwardData {
		probabilityValue := v.Weight
		if v.Store == 0 { //如果库存则为0 则不加入奖项
			probabilityValue = 0
			continue
		}
		if _, ok := this.probabilityVal[v.AwardResult.SerialNumber]; !ok {
			this.probabilitySum += probabilityValue
			this.probabilityVal[v.AwardResult.SerialNumber] = probabilityValue
			this.probabilityData[v.AwardResult.SerialNumber] = v
		}
	}
	if this.EventHandle != nil {
		this.EventHandle.AwardData(this.probabilitySum, this.probabilityVal, this.probabilityData)
	}
	//Log.AppLog.Debug("ruleProbabilityStore [ 总权重 => %f, 每个奖项权重值数据 => %+v,  标识对应的奖品数据: %+v]", this.probabilitySum, this.probabilityVal, this.probabilityData)
}

/**
执行抽奖算法
返回一个奖品标识
*/
func (this *ruleProbabilityStore) algorithm() string {
	serialNumberTemp := ""
	var proNum = this.probabilitySum
	//执行算法

	for k, v := range this.probabilityVal {
		//获取随机数
		randomProbabilityVal := randFloats(1, proNum)
		if randomProbabilityVal <= v {
			serialNumberTemp = k
			break
		} else {
			proNum -= v
		}
	}
	return serialNumberTemp
}

func randFloats(min, max int) int {
	raInt, _ := RandomHelper.RandomAroundInt(min, max)
	return raInt
}
